#include <iostream>
#include <string>
#include <string.h>

using namespace std;

typedef char DataType;

class String{
	public:
		//////////////////////////////////////////////////////////////////////////////////////
		// construct
		String(const char* str = "")
		{
			cout << "Debug# 调用构造函数" << endl;
			_str = new char[strlen(str) + 1];
			_size = _capacity = strlen(str);
			if(NULL == str)
				str = "";
			strcpy(_str, str);
		}

		String(size_t n, DataType data = DataType())
			: _str(new char[n * sizeof(DataType) + 1])
			, _size(0)
			, _capacity(n)
		{
			cout << "Debug# 调用构造函数" << endl;
			while(n--) {
				_str[_size++] = data;
			}
			_str[_size] = '\0';
		}

		void Swap(String& s)
		{
			cout << "Debug# 调用 Swap 函数" << endl;
			swap(_str, s._str);
			swap(_size, s._size);
			swap(_capacity, s._capacity);
		}

		String(const String& s)
			: _str(NULL)
			, _size(0)
			, _capacity(0)
		{
			cout << "Debug# 调用拷贝构造函数——现代写法"<< endl;
			String strTemp(s._str);
			Swap(strTemp);
		}

		//////////////////////////////////////////////////////////////////////////////////////
		// Size
		size_t Size()
		{
			return _size;
		}

		size_t Capacity()
		{
			return _capacity;
		}

		void ReSize(size_t newSize, DataType data)
		{
			cout << "Debug# 调用 ReSize() 函数" << endl;
			size_t oldSize = _size;
			if(newSize < oldSize) {
				cout << "Debug# New Size 小于 Old Size" << endl;
				_size = newSize;
			}
			else {
				if(newSize <= _capacity) {
					cout << "Debug# New Size 小于 Capacity" << endl;
					while(_size < newSize) {
						_str[_size++] = data;
					}
				} else {
					cout << "Debug# New Size 大于 Capacity" << endl;
					String strTemp(newSize, data);
					size_t i = 0;
					for(; i < _size; ++i)
						strTemp._str[i] = _str[i];

					for( ; i < newSize; ++i)
						strTemp._str[i] = data;

					Swap(strTemp);
					_size = oldSize;
				}
			}
		}

		void Reverse()
		{
			cout << "预留空间" << endl;
			return;
		}
		//////////////////////////////////////////////////////////////////////////
		// Modify
		void PushBack(char ch)
		{
			if(_size + 1 >=_capacity) {
				ReSize(_capacity * 2, '\0');
			}
			_str[_size++] = ch;
			_str[_size + 1] = '\0';
			return;
		}

		void PushBack(const char* str)
		{
			size_t len = strlen(str);
			if(_size + len >= _capacity) {
				ReSize(_capacity * 2, '\0');
			}

			size_t index_add = 0;
			while(index_add < len) {
				_str[_size++] = str[index_add++];
			}
		}

		void PopBack()
		{
			--_size;
		}

		void PushFront(char ch)
		{
			if(_size + 1 >= _capacity) {
				// 构造一个临时对象， 大小为
				String strTemp(_capacity *  2, '\0');
				// 将临时空间的有效元素个数置为0便于后面操作
				strTemp._size = 0;
				// 先将字符放进临时对象
				strTemp._str[strTemp._size++] = ch;
				
				// 将原对象中的内容拷贝到临时对象
				size_t i = 0;
				while(i < _size) {
					strTemp._str[strTemp._size++] = _str[i++];
				}
				// 交换
				Swap(strTemp);
			} else {
				size_t i = _size;
				while(i > 0) {
					_str[i] = _str[i - 1];
					--i;
				}
				++_size;
				_str[0] = ch;
			}
		}

		void PopFront()
		{
			size_t i = 1;
			while(i < _size) {
				_str[i - 1] = _str[i];
				++i;
			}
			--_size;
		}

		void Insert(size_t pos, char ch)
		{
			if(_size + 1 >_capacity) {
				ReSize(_capacity * 2, '\0');
			}

			size_t i = _size;
			for(; i >= pos; --i) {
				_str[i] = _str[i - 1];
			}
			_str[pos - 1] = ch;
			++_size;
		}

		void Insert(size_t pos, const char* str)
		{
			size_t len = strlen(str);
			if(_size + len > _capacity) {
				ReSize(_capacity * 2, '\0');
			}

			size_t i = _size;
			for(; i >= pos; --i) {
				_str[i + len] = _str[i];
			}

			size_t j = pos;
			for(i = 0; i < len; ++i) {
				_str[j++] = str[i];
				++_size;
			}
		}

		// 删除从 pos 位置开始的 npos 个元素
		void Erase(size_t pos, size_t npos)
		{
			if(_size <= npos) {
				cout << "There has no npos elements!" << endl;
				return;
			}

			size_t i = pos + npos;
			while(i <= _size) {
				_str[i - npos] = _str[i];
				++i;
			}
			_size -= npos;	
		}

		//////////////////////////////////////////////////////////////////////////
		// Access
		
		const char* C_str()
		{
			return _str;
		}

		size_t Find(char ch)
		{
			if(_size > 0)
			{
				size_t i = 0;
				for(i = 0; i < _size; ++i)
				{
					if(ch == _str[i])
					{
						return i + 1;
					} // end if
				} // end for
				cout << "Not Found " << ch << endl;
			} // end if
		}

		size_t Find(const char* str)
		{
			size_t len = strlen(str);
			if(str == NULL ||_size < len)
				return -1;

			size_t index_str = 0;
			while(_str[index_str] != '\0') {
				if(_str[index_str] == str[0]) {
					size_t index_temp = index_str;
					size_t index_find = 0;
					while(1) {
						if(str[index_find] == '\0') {
							cout << "Find It " << index_str + 1 << endl;
							return index_str + 1;
						}
						if(str[index_find] != _str[index_temp]) {
							cout << "Not Found " << endl;
							break;
						}
						++index_find;
						++index_temp;
					}
				}
				++index_str;
			}
			return -1;
		}

		~String()
		{
			if(_str)
			{
				delete[] _str;
				_str = NULL;
				_size = _capacity = 0;
			}
		}

	public:
		friend ostream& operator<<(ostream& _cout, const String& s);

		DataType& operator[](size_t index)const
		{
			return _str[index - 1];
		}

		String& operator=(const String& s)
		{
			cout << "Debug# Operator '='" << endl;
			if(this != &s)
			{
				String strTemp(s._str);
				Swap(strTemp);
			}
			return *this;
		}

		String operator+(const String& s)
		{
			String strTemp;
			strTemp._str = new DataType[strlen(_str) + strlen(strTemp._str) + 1];
			strcpy(strTemp._str, _str);
			strcat(strTemp._str, s._str);
			return strTemp;
		}

		String& operator+=(char ch)
		{
			cout << "Debug# 调用重载的 += 操作符" << endl;
			String strTemp(_str);
			strTemp._str = new DataType[strlen(_str) + 2];

			strTemp._size = 0;
			size_t i = 0;
			while(i < _size) {
				strTemp._str[strTemp._size++] = _str[i++];
			}

			strTemp._str[_size++] = ch;
			cout << strTemp._str << endl;

			Swap(strTemp);
			return *this;
		}

		String& operator+=(const char* str)
		{
			cout << "调用重载的 += 操作符" << endl;
			String strTemp(_str);
			strTemp._str = new DataType[strlen(str) + _capacity + 1];
			strTemp._capacity = strlen(str) + _capacity + 1;
			strcpy(strTemp._str, _str);

			cout << strTemp._size << endl;

			size_t i = 0;
			strTemp._size = _size;
			for(i = 0; i < strlen(str); ++i) {
				strTemp._str[strTemp._size++] =  str[i];
			}
			Swap(strTemp);
			return *this;
		}

		bool operator>(const String& s)const
		{
			char* s1 = _str;
			char* s2 = s._str;

			while(*s1 == *s2) {
				s1++;
				s2++;
			}
			if(*s1 > *s2) {
				return true;
			}
			return false;
		}

		bool operator<(const String& s)const
		{
			char* s1 = _str;
			char* s2 = s._str;

			while(*s1 == *s2) {
				s1++;
				s2++;
			}
			if(*s1 < *s2) {
				return true;
			}
			return false;
		}

		bool operator>=(const String& s)const
		{
			return !(*this < s);
		}

		bool operator<=(const String& s)const
		{
			return !(*this > s);
		}

		bool operator==(const String& s)const
		{
			return !(*this > s) && !(*this < s);
		}

		bool operator!=(const String& s)const
		{
			return !(*this == s);
		}

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
};

ostream& operator<<(ostream& _cout, const String& s)
{
	_cout << s._str << endl;
	_cout << "    Size : " << s._size << endl;
	_cout << "Capacity : " << s._capacity << endl;

	return _cout;
}

void TestString()
{
	char arr[] = {"ABCDEFG"};
	//size_t size = sizeof(arr)/sizeof(arr[0]);

	String s0(arr);
	cout << "      s0 : " << s0 << endl;

	String s1(5, 'A');
	cout << "      s1 : " << s1 << endl;
//
//	String s2 = s1;
//	cout << "      s2 : " << s2 << endl;
//
//	cout << s0[3] << endl;
//
//	s0.Find("CDE");
//
//	cout << "#########################################" << endl;
//	cout << "      s0 : " <<s0 << endl;
	s0.PushBack('a');
//	s0.PushBack('b');
//	s0.PushBack('c');
//	s0.PushBack('d');
//	s0.PushBack('e');
//	s0.PushBack('f');
	cout << "      s0 : " << s0 << endl;

	s0.PushBack(" Hello");
	cout << "      s0 : " << s0 << endl;
	s0.PushBack(" World");
	cout << "      s0 : " << s0 << endl;

	s0.PushFront('!');
	cout << "      s0 : " << s0 << endl;
	s0.PushFront('@');
	cout << "      s0 : " << s0 << endl;
	s0.PushFront('#');
	cout << "      s0 : " << s0 << endl;
	s0.PushFront('$');
	cout << "      s0 : " << s0 << endl;
	s0.PushFront('%');
	cout << "      s0 : " << s0 << endl;

	s0.PopFront();
	s0.PopFront();
	s0.PopFront();
	cout << "      s0 : " << s0 << endl;

	s0.Insert(3, ' ');
	s0.Insert(3, '1');
	s0.Insert(3, '2');
	s0.Insert(3, '3');
	s0.Insert(3, '4');
	s0.Insert(3, '5');
	s0.Insert(3, '6');
	s0.Insert(3, '7');
	s0.Insert(3, ' ');
	cout << "      s0 : " << s0 << endl;

	s0.Insert(2, " Are You Ok ");
	cout << "      s0 : " << s0 << endl;

	s0.Erase(2, 12);
	cout << "      s0 : " << s0 << endl;

	s0 += 'V';
	cout << "      s0 : " << s0 << endl;

	s0 += " Money Money ";
	cout << "      s0 : " << s0 << endl;

	cout << " compare : " << (s0 > s1) << endl;
}

int main()
{
	TestString();
	return 0;
}
